//
//  AppGraphManager.h
//  AppGraphManager is a thread that manages a simple directed graph
//  2006 John Wiggins
//
// This program is free software; you can redistribute it and/or modify  
// it under the terms of the GNU General Public License as published by  
// the Free Software Foundation; either version 2 of the License, or     
// (at your option) any later version.                                   
// 
// This program is distributed in the hope that it will be useful,       
// but WITHOUT ANY WARRANTY; without even the implied warranty of        
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         
// GNU General Public License for more details.                          
//     
//     You should have received a copy of the GNU General Public License     
//     along with this program; if not, write to the                         
//         Free Software Foundation, Inc.,                                       
//         59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.  
//-------------------------------------------------------------
#ifndef APP_GRAPH_MANAGER_H
#define APP_GRAPH_MANAGER_H
//-------------------------------------------------------------
#include <list>
#include <map>
#include <utility>

#include "App/AppMixerThread.h"
#include "App/AppPlugin.h"
#include "App/AppSourceThread.h"
#include "Basics/BasTypes.h"
#include "Ipc/IpcMessage.h"
//-------------------------------------------------------------
using std::list;
using std::map;
using std::binary_function;
//-------------------------------------------------------------
class AppGraphManager
{
public:
                        AppGraphManager                 ();
                        ~AppGraphManager                ();
    
    ipc_port_t          portId                          () const { return mMsgPort; }

private:
    
    struct GraphVert {
                        GraphVert( void *inst, ge_plugin_type type, ipc_port_t port, uint32 mIn,
                                    uint32 uIn, uint32 mOut, uint32 uOut )
                        : mInstance( inst ), mType( type ), mPort( port ), mMaxInputs( mIn )
                        , mMaxOutputs( mOut ), mUsedInputs( uIn ), mUsedOutputs( uOut )
                        {}
    // plugin instance
        void *          mInstance;
    // the plugin's type
        ge_plugin_type  mType;
    // port id ( for the source or mixer that owns it )
        ipc_port_t      mPort;
    // max # of inputs
        uint32          mMaxInputs;
    // max # of outputs
        uint32          mMaxOutputs;
    // used # of inputs
        uint32          mUsedInputs;
    // used # of outputs
        uint32          mUsedOutputs;
    };
    
    typedef                 list< GraphVert * >         GraphVertPtrList;
    
    static void *           start_loop                  ( void * data );
    void *                  main_loop                   ();
    
    void                    receiveMessages             ();
    void                    handleMessage               ( IpcMessage *msg );

    void                    addSource                   ( void * instance );
    void                    addMixer                    ( void * instance );
    void                    addFilter                   ( void * instance );
    void                    addOutput                   ( void * instance );

    void                    removeSource                ( void * instance, ipc_port_t port );
    void                    removeMixer                 ( void * instance, ipc_port_t port );
    void                    removeFilter                ( void * instance, ipc_port_t port );
    void                    removeOutput                ( void * instance, ipc_port_t port );

    void                    addNode                     ( ge_plugin_type type, void * instance );
    void                    removeNode                  ( ge_plugin_type type, void * instance );

    bool                    addEdge                     ( void * from, void * to );
    bool                    removeEdge                  ( void * from, void * to );

    bool                    removeGraphEdge             ( GraphVert *fromVert, GraphVert *toVert );
    void                    removeAllGraphEdgesForNode  ( GraphVert *vert );
    
    uint32                  countUpstreamMixers         ( GraphVert *vert );
    GraphVert *             findUpstreamSourceOrMixer   ( GraphVert *vert );
    void                    findAllUpstreamMixers       ( GraphVert *vert, GraphVertPtrList & mixers );
    void                    getDirectlyAttachedMixers   ( GraphVert *vert, GraphVertPtrList & mixers );
    void                    sendDisconnectionMessage    ( GraphVert *fromVert, GraphVert *toVert );
    void                    sendConnectionMessage       ( GraphVert *fromVert, GraphVert *toVert );
    void                    notifySourceOfFilterChain   ( GraphVert *srcVert );
    void                    notifySourceOfOutput        ( GraphVert *srcVert );
    void                    notifyMixerOfFilterChain    ( GraphVert *mixVert );
    void                    notifyMixerOfSource         ( GraphVert *mixVert, GraphVert *srcVert );
    void                    confirmMixerResidency       ( GraphVert *mixVert );
    void                    updateMixerOrder            ( GraphVert *mixVert );
    void                    notifyMixerThreadOfOutput   ( GraphVert *outVert );

    // graph data
    GraphVertPtrList        mVertList;
    map<GraphVert*, GraphVertPtrList> mOutEdgeMap;
    map<GraphVert*, GraphVertPtrList> mInEdgeMap;
    // thread pools
    list<AppSourceThread*>  mSourceThreads;
    AppMixerThread *        mMixerThread;
    pthread_t               mThread;
    ipc_port_t              mMsgPort;
    bool                    mQuitting;
};
//-------------------------------------------------------------
#endif // APP_GRAPH_MANAGER_H
//-------------------------------------------------------------
